using UnityEngine;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;

namespace JEngine.Framework
{
    public static class Engine
    {
        #region API

        private static EngineBehaviour _engineBehaviour;

        private static readonly EngineHelper helper = new EngineHelper();
        private static readonly HttpServer httpServer = new HttpServer();
        private static readonly MathfHelper mathfHelper = new MathfHelper();
        private static readonly FileHelper fileHelper = new FileHelper();
        private static readonly ResourceManager resManager = new ResourceManager();
        private static readonly PanelManager uiManager = new PanelManager();
        private static readonly AASystem aa = new AASystem();

        #endregion

        private static RayHelper ray;

        public static EngineHelper HELP => helper;
        public static HttpServer HTTP => httpServer;
        public static MathfHelper Mathf => mathfHelper;
        public static FileHelper Flie => fileHelper;
        public static PanelManager UI => uiManager;
        public static ResourceManager Res => resManager;
        public static RayHelper Ray => ray;
        public static AASystem AA => aa;
        public static DownTask DownTask => new DownTask();

        public static ushort GetTypeID(Type type) =>
            (ushort) (type.FullName.GetStableHashCode() & 0xFFFF);


        #region 得到程序集

        public static Type[] appAssembly;
        private static Dictionary<Type, List<Type>> attributeDic = new Dictionary<Type, List<Type>>();
        private static Dictionary<Type, List<Type>> interfacesDic = new Dictionary<Type, List<Type>>();
        private static Dictionary<Type, List<Type>> classDic = new Dictionary<Type, List<Type>>();


        public static List<Type> GetParentClass<parent>() where parent : class
        {
            if (classDic.ContainsKey(typeof(parent)))
                return classDic[typeof(parent)];
            Type parentType = typeof(parent);

            classDic.Add(typeof(parent), new List<Type>());
            foreach (var type in appAssembly)
            {
                if (parentType.IsAssignableFrom(type) && type != parentType && !type.IsAbstract)
                    classDic[typeof(parent)].Add(type);
            }

            return classDic[typeof(parent)];
        }

        //反射特性  
        public static List<Type> GetAttribute<Attri>() where Attri : Attribute
        {
            if (attributeDic.ContainsKey(typeof(Attri)))
                return attributeDic[typeof(Attri)];
            attributeDic.Add(typeof(Attri), new List<Type>());
            foreach (var type in appAssembly)
            {
                Attri att = type.GetCustomAttribute<Attri>();
                if (att != null && !type.IsAbstract)
                    attributeDic[typeof(Attri)].Add(type);
            }

            return attributeDic[typeof(Attri)];
        }

        //反射接口
        public static List<Type> GetInterfaces<Inter>()
        {
            if (interfacesDic.ContainsKey(typeof(Inter)))
                return attributeDic[typeof(Inter)];
            attributeDic.Add(typeof(Inter), new List<Type>());
            foreach (var type in appAssembly)
            {
                Type[] implementedInterfaces = type.GetInterfaces();
                if (implementedInterfaces.Contains(typeof(Inter)) && !type.IsAbstract)
                    attributeDic[typeof(Inter)].Add(type);
            }

            return attributeDic[typeof(Inter)];
        }

        private static Type[] GetAppAssembly()
        {
            List<Type> types = new List<Type>();
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                try
                {
                    // 获取程序集中的类型
                    Type[] ts = assembly.GetTypes(); // GetTypes() 代替 GetExportedTypes()
                    types.AddRange(ts);
                }
                catch (Exception ex)
                {
                    // 处理可能的异常，忽略不支持的程序集
                    Debug.LogWarning($"Error loading types from assembly {assembly.FullName}: {ex.Message}");
                }
            }

            return types.ToArray();
        }

        #endregion

        public static void RegisterTimer(UpdateTimerCallback callback)
        {
            _engineBehaviour.RegisterTimer(callback);
        }

        public static void UnRegisterTimer(UpdateTimerCallback callback)
        {
            _engineBehaviour.UnRegisterTimer(callback);
        }

        [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
        private static void Start()
        {
            var game = new GameObject("=======JEngine=======", typeof(EngineBehaviour));
            _engineBehaviour = game.GetComponent<EngineBehaviour>();
            UnityEngine.Object.DontDestroyOnLoad(game);
            appAssembly = GetAppAssembly();
            ray = new RayHelper();
            RegisterTimer(ray.Update);

            Debug.Log("================JEngine Start================");
        }
    }
}